package com.hhwy.components;

import com.hhwy.HslCommunication.Core.Types.OperateResult;
import com.hhwy.HslCommunication.Profinet.Siemens.SiemensPLCS;
import com.hhwy.HslCommunication.Profinet.Siemens.SiemensS7Net;
import com.hhwy.domain.CableConveyorsMain;
import com.hhwy.domain.CableConveyorsSub;
import com.hhwy.domain.CableConveyorsSubConfig;
import com.hhwy.service.ICableConveyorsMainService;
import com.hhwy.service.ICableConveyorsSubConfigService;
import com.hhwy.service.ICableConveyorsSubService;
import com.hhwy.utils.SpringBeanUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class CableConveyorsTimer {

    @Value("${cable-conveyors-socket.ip}")
    private String ip;

    @Value("${cable-conveyors-socket.enable}")
    private boolean enable;

    @Autowired
    private ICableConveyorsSubConfigService cableConveyorsSubConfigService;

    private static final ConcurrentLinkedQueue<CableConveyorsMain> mainDataList = new ConcurrentLinkedQueue<>();
    private static final ConcurrentLinkedQueue<CableConveyorsSub> subDataList = new ConcurrentLinkedQueue<>();

    private static final ThreadPoolExecutor threadpool = new ThreadPoolExecutor(15, 15,
            10L, TimeUnit.SECONDS, new LinkedBlockingQueue<>());

    private static final ConcurrentLinkedQueue<SiemensS7Net> SiemensS7NetList = new ConcurrentLinkedQueue<>();

    private static String staticIp;
    private static boolean staticEnable;

    @PostConstruct
    public void init() {
        staticIp = this.ip;
        staticEnable = this.enable;
        startSubControllerThreads();
    }


    private static SiemensS7Net getSiemensS7Net(){
        SiemensS7Net siemens_net= SiemensS7NetList.poll();
        if(null==siemens_net){
            siemens_net = new SiemensS7Net(SiemensPLCS.S1200, staticIp);
            OperateResult connect = siemens_net.ConnectServer();
            if (connect.IsSuccess) {
                log.info("电缆输送机 connect success!");
                return siemens_net;
            } else {
                log.info("电缆输送机 connect failed:" + connect.Message);
                return null;
            }
        }
//        siemens_net.ConnectClose();
        return siemens_net;
    }
    private static void releaseSiemensS7Net(SiemensS7Net net){
        SiemensS7NetList.offer(net);
    }

//    // 启动9个线程来读取分控机的数据,@PostConstruct 注解的方法会在依赖注入完成后自动执行一次。
    public void startSubControllerThreads() {
        if (staticEnable) {
            List<CableConveyorsSubConfig> configs=cableConveyorsSubConfigService.list();
            for (CableConveyorsSubConfig config:configs) {
                threadpool.execute(new SubControllerReader(ip, config));
            }
        }
    }

    @Scheduled(cron="0/1 * *  * * ? ")
    public void main() {
        if (staticEnable) {
//            SiemensS7Net siemens_net = new SiemensS7Net(SiemensPLCS.S1200, ip);
//            OperateResult connect = siemens_net.ConnectServer();
//            if (connect.IsSuccess) {
//                log.info("电缆输送机 connect success!");
//            } else {
//                log.info("电缆输送机 connect failed:" + connect.Message);
//                return;
//            }
//            siemens_net.ConnectClose();
            SiemensS7Net siemens_net=getSiemensS7Net();
            if(null==siemens_net){
                log.error("获取主控数据时，西门子服务连接获取失败。");
                return;
            }
            // 读取主控数据的逻辑
            Boolean I0_0 = siemens_net.ReadBool("I0.0").Content;
            Boolean M10_1 = siemens_net.ReadBool("M10.1").Content;
            Boolean I0_4 = siemens_net.ReadBool("I0.4").Content;
            Boolean M11_0 = siemens_net.ReadBool("M11.0").Content;
            Boolean M11_1 = siemens_net.ReadBool("M11.1").Content;
            Boolean M11_2 = siemens_net.ReadBool("M11.2").Content;
            Float M20 = siemens_net.ReadFloat("M20").Content;
            Float M40 = siemens_net.ReadFloat("M40").Content;

            CableConveyorsMain cabConveyorsMain = new CableConveyorsMain();
            cabConveyorsMain.setIO0(I0_0);
            cabConveyorsMain.setM10_1(M10_1);
            cabConveyorsMain.setI0_4(I0_4);
            cabConveyorsMain.setM11_0(M11_0);
            cabConveyorsMain.setM11_1(M11_1);
            cabConveyorsMain.setM11_2(M11_2);
            if (M20 != null) {
                BigDecimal bigDecimalPrice = new BigDecimal(M20).setScale(1, RoundingMode.DOWN);
                cabConveyorsMain.setM20(bigDecimalPrice.floatValue());
            }
            if (M40 != null) {
                BigDecimal bigDecimalPrice = new BigDecimal(M40).setScale(1, RoundingMode.DOWN);
                cabConveyorsMain.setM40(bigDecimalPrice.floatValue());
            }
            cabConveyorsMain.setCreateTime(new Date());

            mainDataList.add(cabConveyorsMain);
            log.info(cabConveyorsMain.toString());

            releaseSiemensS7Net(siemens_net);
        }
    }

    @Scheduled(cron="0/5 * *  * * ? ")
    public void CableConveyorsMainDataSave() {
        if (staticEnable) {
            try {
                if (mainDataList.size() > 10) {
                    ICableConveyorsMainService cableConveyorsMainService = SpringBeanUtils.getApplicationContext().getBean(ICableConveyorsMainService.class);
                    cableConveyorsMainService.saveBatch(new ArrayList<>(mainDataList));
                    mainDataList.clear();
                }
            } catch (Exception e) {
                log.error("Error saving cableConveyorsMain data", e);
            }
        }
    }

    @Scheduled(cron="0/5 * *  * * ? ")
    public void CableConveyorsSubDataSave() {
        if (staticEnable) {
            try {
                if (subDataList.size() > 10) {
                    ICableConveyorsSubService cableConveyorsSubService = SpringBeanUtils.getApplicationContext().getBean(ICableConveyorsSubService.class);
                    cableConveyorsSubService.saveBatch(new ArrayList<>(subDataList));
                    subDataList.clear();
                }
            } catch (Exception e) {
                log.error("Error saving cableConveyorsSub data", e);
            }
        }
    }


    private static class SubControllerReader implements Runnable {

        private final String ip;
        private final CableConveyorsSubConfig config;
        public SubControllerReader(String ip, CableConveyorsSubConfig config) {
            this.ip = ip;
            this.config=config;
        }

        @Override
        public void run() {
            while (true){
//                SiemensS7Net siemens_net = new SiemensS7Net(SiemensPLCS.S1200, ip);
//            OperateResult connect = siemens_net.ConnectServer();
//            if (connect.IsSuccess) {
//                log.info("电缆输送机 connect success!");
//            } else {
//                log.info("电缆输送机 connect failed:" + connect.Message);
//                return;
//            }
//            siemens_net.ConnectClose();
                SiemensS7Net siemens_net=getSiemensS7Net();
                if(null!=siemens_net) {
                    try {
                        //本地远程
                        Boolean localOrRemote = siemens_net.ReadBool(config.getLocalOrRemote()).Content;
                        //前进后退
                        Boolean forwardOrBackoff = siemens_net.ReadBool(config.getForwardOrBackoff()).Content;
                        //心跳
                        Boolean heartBeat = siemens_net.ReadBool(config.getHeartBeat()).Content;
                        //速度+
                        Boolean speed0 = siemens_net.ReadBool(config.getSpeed0()).Content;
                        //速度-
                        Boolean speed1 = siemens_net.ReadBool(config.getSpeed1()).Content;
                        //485通讯故障
                        Boolean communicationFailures485 = siemens_net.ReadBool(config.getCommunicationFailures485()).Content;
                        //急停
                        Boolean emergencyStop = siemens_net.ReadBool(config.getEmergencyStop()).Content;
                        //站号
                        Integer stationNumber = siemens_net.ReadInt16(config.getStationNumber()).Content.intValue();
                        //变频器1电压
                        Integer inverterVoltage1 = siemens_net.ReadInt16(config.getInverterVoltage1()).Content.intValue();
                        //变频器2电压
                        Integer inverterVoltage2 = siemens_net.ReadInt16(config.getInverterVoltage2()).Content.intValue();
                        //变频器1电流
                        Float inverterCurrent1 = siemens_net.ReadFloat(config.getInverterCurrent1()).Content;
                        //变频器2电流
                        Float inverterCurrent2 = siemens_net.ReadFloat(config.getInverterCurrent2()).Content;
                        //变频器1频率
                        Float inverterFrequency1 = siemens_net.ReadFloat(config.getInverterFrequency1()).Content;
                        //变频器2频率
                        Float inverterFrequency2 = siemens_net.ReadFloat(config.getInverterFrequency2()).Content;
                        //变频器1故障代码
                        Integer inverterFailuresCode1 = siemens_net.ReadInt16(config.getInverterFailuresCode1()).Content.intValue();
                        //变频器2故障代码
                        Integer inverterFailuresCode2 = siemens_net.ReadInt16(config.getInverterFailuresCode2()).Content.intValue();
                        //速度
                        Float speed = siemens_net.ReadFloat(config.getSpeed()).Content;

                        if(inverterCurrent1==0 && inverterCurrent2==0){
                            releaseSiemensS7Net(siemens_net);
                            continue;
                        }

                        CableConveyorsSub cableConveyorsSub = new CableConveyorsSub();
                        cableConveyorsSub.setCreateTime(new Date());
                        cableConveyorsSub.setSubId(config.getId());
                        cableConveyorsSub.setName(config.getName());
                        cableConveyorsSub.setLocalOrRemote(localOrRemote);
                        cableConveyorsSub.setForwardOrBackoff(forwardOrBackoff);
                        cableConveyorsSub.setHeartBeat(heartBeat);
                        cableConveyorsSub.setSpeed0(speed0);
                        cableConveyorsSub.setSpeed1(speed1);
                        cableConveyorsSub.setCommunicationFailures485(communicationFailures485);
                        cableConveyorsSub.setEmergencyStop(emergencyStop);
                        cableConveyorsSub.setStationNumber(stationNumber);
                        cableConveyorsSub.setInverterVoltage1(inverterVoltage1);
                        cableConveyorsSub.setInverterVoltage2(inverterVoltage2);
                        if (inverterCurrent1 != null) {
                            BigDecimal bigDecimalPrice = new BigDecimal(inverterCurrent1).setScale(1, RoundingMode.DOWN);
                            cableConveyorsSub.setInverterCurrent1(bigDecimalPrice.floatValue());
                        }
                        if (inverterCurrent2 != null) {
                            BigDecimal bigDecimalPrice = new BigDecimal(inverterCurrent2).setScale(1, RoundingMode.DOWN);
                            cableConveyorsSub.setInverterCurrent2(bigDecimalPrice.floatValue());
                        }
                        if (inverterFrequency1 != null) {
                            BigDecimal bigDecimalPrice = new BigDecimal(inverterFrequency1).setScale(2, RoundingMode.DOWN);
                            cableConveyorsSub.setInverterFrequency1(bigDecimalPrice.floatValue());
                        }
                        if (inverterFrequency2 != null) {
                            BigDecimal bigDecimalPrice = new BigDecimal(inverterFrequency2).setScale(2, RoundingMode.DOWN);
                            cableConveyorsSub.setInverterFrequency2(bigDecimalPrice.floatValue());
                        }
                        cableConveyorsSub.setInverterFailuresCode1(inverterFailuresCode1);
                        cableConveyorsSub.setInverterFailuresCode2(inverterFailuresCode2);
                        if (speed != null) {
                            BigDecimal bigDecimalPrice = new BigDecimal(speed).setScale(1, RoundingMode.DOWN);
                            cableConveyorsSub.setSpeed(bigDecimalPrice.floatValue());
                        }

                        subDataList.add(cableConveyorsSub);
                        log.info(cableConveyorsSub.toString());

                        releaseSiemensS7Net(siemens_net);

                        Thread.sleep(1000);

                    } catch (Exception e) {
                        log.error("分控机读取数据失败", e.getMessage());
                    }
                }else{
                    log.error("获取"+config.getName()+"数据时，西门子服务连接获取失败。");
                }
            }
//

        }
    }
}
